package lx;

import java.util.ArrayList;

public class demo1 {
    /*
          需求：
              定义一个继承结构：
                                  动物
                       |                           |
                       猫                          狗
                    |      |                    |      |
                 波斯猫   狸花猫                泰迪   哈士奇
               属性：名字，年龄
               行为：吃东西
                     波斯猫方法体打印：一只叫做XXX的，X岁的波斯猫，正在吃小饼干
                     狸花猫方法体打印：一只叫做XXX的，X岁的狸花猫，正在吃鱼
                     泰迪方法体打印：一只叫做XXX的，X岁的泰迪，正在吃骨头，边吃边蹭
                     哈士奇方法体打印：一只叫做XXX的，X岁的哈士奇，正在吃骨头，边吃边拆家

          测试类中定义一个方法用于饲养动物
              public static void keepPet(ArrayList<???> list){
                  //遍历集合，调用动物的eat方法
              }
          要求1：该方法能养所有品种的猫，但是不能养狗
          要求2：该方法能养所有品种的狗，但是不能养猫
          要求3：该方法能养所有的动物，但是不能传递其他类型
       */
    public static void main(String[] args) {
        HuskyDog h = new HuskyDog("哈士奇", 1);
        LihuaCat l = new LihuaCat("狸花猫", 2);
        PersianCat p = new PersianCat("波斯猫", 3);
        TeddyDog t = new TeddyDog("泰迪", 4);
        ArrayList<LihuaCat> list1 = new ArrayList<>();
        ArrayList<PersianCat> list2 = new ArrayList<>();
        // 向列表中添加一些猫的实例
        list1.add(l);
        list2.add(p);
        //调用方法
        keepPet1(list1);
        keepPet1(list2);
        System.out.println("-------------------------------------------");
        ArrayList<HuskyDog> list3 = new ArrayList<>();
        ArrayList<TeddyDog> list4 = new ArrayList<>();
        // 向列表中添加一些狗的实例
        list3.add(h);
        list4.add(t);
        //调用方法
        keepPet2(list3);
        keepPet2(list4);
        System.out.println("-------------------------------------------");
        list1.add(l);
        list2.add(p);
        list3.add(h);
        list4.add(t);
        keepPet3(list1);
        keepPet3(list2);
        keepPet3(list3);
        keepPet3(list4);
    }


    /*
    此时我们就可以使用泛型的通配符：
      ?也表示不确定的类型
      他可以进行类型的限定
      ? extends E: 表示可以传递E或者E所有的子类类型
     ? super E:表示可以传递E或者E所有的父类类型
     */
    //  要求1：该方法能养所有品种的猫，但是不能养狗
    public static void keepPet1(ArrayList<? extends Cat> list) {
        //遍历集合，调用动物的eat方法
        for (Cat cat : list) {
            cat.eat();
        }
    }
    //  要求2：该方法能养所有品种的狗，但是不能养猫
    public static void keepPet2(ArrayList<? extends Dog> list) {
        //遍历集合，调用动物的eat方法
        for (Dog dog : list) {
            dog.eat();
        }
    }

    //  要求3：该方法能养所有的动物，但是不能传递其他类型
    public static void keepPet3(ArrayList<? extends Animal> list) {
        //遍历集合，调用动物的eat方法
        for (Animal animal : list) {
            animal.eat();
        }
    }
}
